package com.cr.dataprotect.interceptor;


import com.baomidou.mybatisplus.core.toolkit.PluginUtils;

import com.cr.dataprotect.bean.ProviderConfigBean;
import com.cr.dataprotect.manage.DesensitizationManage;
import com.cr.dataprotect.manage.IntegrityManage;
import com.cr.dataprotect.manage.SensitiveManage;
import com.cr.dataprotect.provider.AbstractProvider;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.MapUtils;
import org.apache.ibatis.executor.parameter.ParameterHandler;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.mapping.SqlCommandType;
import org.apache.ibatis.plugin.*;
import org.apache.ibatis.reflection.MetaObject;
import org.apache.ibatis.reflection.SystemMetaObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

import java.sql.PreparedStatement;
import java.util.Objects;
import java.util.Properties;

/**
 * 拦截Mybatis ParameterHandler，在插入和更新时，进行数据保护
 * <p>
 * 执行顺序 1.敏感字段 2.完整性保护
 *
 * @author ChenRui
 * @date 2023.12.5
 */
@Intercepts({
        @Signature(type = ParameterHandler.class, method = "setParameters", args = {PreparedStatement.class})})
@Slf4j
@Order(2)
@Component
public class DataInterceptor extends AbstractProvider implements Interceptor {
    @Autowired
    private SensitiveManage sensitiveManage;
    @Autowired
    private IntegrityManage integrityManage;
    @Autowired
    private DesensitizationManage desensitizationManage;

    @Override
    @SuppressWarnings({"unchecked", "rawtypes"})
    public Object intercept(Invocation invocation) throws Throwable {
        if (!super.hasProvider()) {
            //如果没配置敏感字段，不需要处理
            return invocation.proceed();
        }

        ParameterHandler parameterHandler = (ParameterHandler) PluginUtils.realTarget(invocation.getTarget());
        MetaObject metaObject = SystemMetaObject.forObject(parameterHandler);
        MappedStatement mappedStatement = (MappedStatement) metaObject.getValue("mappedStatement");
        SqlCommandType sqlCommandType = mappedStatement.getSqlCommandType();

        if (sqlCommandType == SqlCommandType.INSERT || sqlCommandType == SqlCommandType.UPDATE) {

            //处理更新数据的情况，对表中的字段进行处理
            Object parameterObject = parameterHandler.getParameterObject();
            if (Objects.nonNull(parameterObject)) {
                //1.获取配置文件的配置
                ProviderConfigBean providerConfigBean = super.loadAllFieldConfig();
                //2.1.先执行字段加密
                if (MapUtils.isNotEmpty(providerConfigBean.getSensitive())) {
                    sensitiveManage.sensitiveParameter(invocation, providerConfigBean.getSensitive());
                }
                //2.2.后对加密的值进行完整性保护
                if (MapUtils.isNotEmpty(providerConfigBean.getIntegrity())) {
                    integrityManage.handleIntegrity( invocation, providerConfigBean.getIntegrity());
                }

            }
        }
        return invocation.proceed();
    }

    @Override
    public Object plugin(Object target) {
        if (target instanceof ParameterHandler) {
            return Plugin.wrap(target, this);
        }
        return target;
    }

    @Override
    public void setProperties(Properties properties) {
        //empty method
    }

}
